import React, { Fragment, useEffect, useRef } from "react"
import Taro, { useShareAppMessage, useRouter } from "@tarojs/taro"
import { Image, View, Swiper, SwiperItem } from "@tarojs/components"
import { Divider } from "@taroify/core"
import GpContainer from "@/components/GpContainer"
import {
  commentNote,
  concernPerson,
  getNoteComments,
  GetNoteDetail,
  noteLikeSwitch,
  reportComment,
  switchNoteCollect
} from "@/apis/yikao-community"
import { requestIsFullfilled } from "@/utils/request"
import { useSetState } from "@/utils/hooks"
import { dateFormat } from "@/utils/common"
import { getWindowInfo } from "@/utils/core"
import GpNoteItem from "../components/GpNoteItem"
import GpOpinion from "../components/GpOpinion"
import styles from "./index.module.scss"
import GpFlowModule from "../components/GpFlowModule"
import GpWordItem from "../components/GpWordItem"
import GpComment from "../components/GpComment"
import { navigation } from "@/utils/router"
import { pageMapperCommunity } from "@/constants/pageMap"
import NoteAnswer from "../../home/components/noteAnswer"
import { authActionHandler } from "@/utils/app"
import clsx from "clsx"
import { notePatchStack } from "@/constants/note"

interface INoteComment extends IApiRelative.IGetNoteComments.IGetNoteCommentItem {
  [key: string]: any
}
type IParams = {
  /** 笔记id */
  id: string
  /** 跳转来源
   * @description "worddetail" 话题详情
   */
  from?: "worddetail"
  /** 当从话题详情点击进入时的那个话题id */
  topicId?: string
}
type IState = {
  detail: IApiRelative.IGetNoteDetail.INoteDetail
  currentImage: number
  /** 图片显示区的高度，默认和swiper默认高度一致 */
  imageHeight: number
  extend: boolean
  /** 笔记评论列表 */
  noteComments: INoteComment[]
  /** 顶级评论是否有更多
   * @default true
   */
  topNoteHasMore: boolean
  /** 顶级评论当前页码
   * @default 1
   */
  topNoteCurrent: number
  /** 评论数 */
  commentCount: number
}
/**
 * @page 笔记详情/话题详情进入笔记详情/短评详情
 * @description 判断条件如下:
 * - 笔记详情: router.params.from === "worddetail" && Boolean(router.params.topicId)
 * - 短评详情: 笔记详情返回isShort为true
 * - 笔记详情: 其他情况
 */
export default function NoteDetail() {
  const swiperMaxHeight = 500
  const router = useRouter<IParams>()
  const opinionRef = useRef<IOpinionRef>()
  const [state, setState, stateRef] = useSetState<IState>(
    {
      detail: {
        files: [],
        tagValues: [],
        tags: [],
        modules: [],
        recommendNotes: [],
        contentFragments: []
      } as any,
      currentImage: 1,
      imageHeight: 300,
      extend: false,
      noteComments: [],
      topNoteCurrent: 1,
      topNoteHasMore: true,
      commentCount: 0
    },
    true
  )
  useShareAppMessage(() => {
    return {}
  })
  useEffect(() => {
    fetchDetail()
    fetchNoteComments()
  }, [])
  function fetchDetail() {
    Taro.showLoading({ title: "加载中" })
    const params = {} as any
    if (router.params.from === "worddetail") {
      params.discussionId = router.params.topicId
    }
    GetNoteDetail({ id: Number(router.params.id) }, params)
      .then(res => {
        if (requestIsFullfilled(res)) {
          const detail = res.data.data
          if (detail.updatedTime) detail.updatedTimeFormated = dateFormat(detail.publishedTime)
          // 处理笔记文本内容 根据换行符进行切割成段落
          if (detail.content) {
            detail.contentFragments = detail.content.split(/\r?\n/)
          } else {
            detail.contentFragments = []
          }
          // 处理推荐笔记&更多回答(都是仅显示6个)
          if (detail.recommendNotes && detail.recommendNotes.length > 0) {
            detail.recommendNotes = detail.recommendNotes.slice(0, 6)
          }
          setState({ detail })
          if (detail.isShort) {
            Taro.setNavigationBarTitle({
              title: "短评详情"
            })
          }
          if (detail.files.length > 0) {
            function calImageSize(originalWidth: number, originalHeight: number) {
              const windowWidth = getWindowInfo().width
              let height = (originalHeight / originalWidth) * windowWidth
              let extend = false
              if (height <= swiperMaxHeight) {
                extend = false
              } else {
                height = swiperMaxHeight
                extend = true
              }
              setState({ imageHeight: height, extend })
            }
            const { fileImage: url, width, height } = detail.files[0]
            if (width && height) {
              calImageSize(width, height)
            } else {
              Taro.getImageInfo({
                src: url,
                success(result) {
                  calImageSize(result.width, result.height)
                }
              })
            }
          }
        }
      })
      .finally(() => {
        Taro.hideLoading()
      })
  }
  function actionNoteComments(current: number, pageSize: number, parentId?: number) {
    return getNoteComments(
      {
        id: router.params.id,
        parentId
      },
      {
        pagination: {
          current,
          pageSize
        },
        search: {},
        sort: {
          predicate: "",
          reverse: false
        }
      }
    )
  }
  /** 添加前端必要字段 */
  function patchFields(
    comment: IApiRelative.IGetNoteComments.IGetNoteCommentItem,
    childNoteHasMore = true
  ) {
    if (typeof comment.childNoteCurrent === "undefined") {
      comment.childNoteCurrent = 0
    }
    if (typeof comment.childNoteHasMore === "undefined") {
      comment.childNoteHasMore = childNoteHasMore
    }
    if (typeof comment.children === "undefined") {
      comment.children = []
    }
  }
  /** 获取评论列表
   * @param {number} [parentId=0] 父级评论id
   */
  function fetchNoteComments(parentId?: number) {
    if (!parentId) {
      actionNoteComments(stateRef.current!.topNoteCurrent, 10).then(res => {
        if (requestIsFullfilled(res)) {
          const { list, pagination } = res.data.data
          list.forEach(l => {
            patchFields(l, l.childrenCount > 0)
          })
          setState({
            // @ts-ignore
            noteComments:
              pagination.current === 1 ? list : stateRef.current!.noteComments.concat(list),
            topNoteHasMore: pagination.current < pagination.pageCount,
            commentCount: pagination.total
          })
        }
      })
    } else {
      const _noteComments = stateRef.current!.noteComments.concat()
      const parent = _noteComments.find(item => item.id === parentId)
      if (parent) {
        patchFields(parent)
        parent.childNoteCurrent += 1
        actionNoteComments(parent.childNoteCurrent, 5, parentId).then(res => {
          if (requestIsFullfilled(res)) {
            const { list, pagination } = res.data.data
            const _children = pagination.current === 1 ? list : parent.children.concat(list)
            parent.children = _children
            parent.childNoteHasMore = pagination.current < pagination.pageCount
            setState({
              // @ts-ignore
              noteComments: _noteComments
            })
          }
        })
      }
    }
  }
  function handleConcern() {
    authActionHandler(handleConcernAction, {
      mobile: true,
      avatarAndNickname: false
    })
  }
  function handleConcernAction() {
    if (!state.detail) return
    concernPerson({
      miniVisitorId: state.detail.miniVisitorId
    }).then(res => {
      if (requestIsFullfilled(res)) {
        const isCancel = state.detail.isSelfFollowing
        Taro.showToast({
          title: isCancel ? "已取消关注" : "关注成功",
          icon: "none"
        })
        const _detail = { ...state.detail }
        _detail.isSelfFollowing = !_detail.isSelfFollowing
        _detail.followerCount = _detail.followerCount + (isCancel ? -1 : 1)
        setState({
          detail: _detail
        })
      }
    })
  }
  function handleReply(commentId: number, parentId?: number) {
    if (opinionRef.current) {
      opinionRef.current.triggerComment(commentId, false, parentId)
    }
  }
  function handleReport(commentId: number, _parentId?: number) {
    reportComment(
      {
        id: commentId
      },
      {}
    ).then(res => {
      if (requestIsFullfilled(res)) {
        Taro.showToast({
          title: "举报成功",
          icon: "none"
        })
      }
    })
  }
  /** 顶级点评的action(如 点评笔记, 点评资讯) */
  function topCommentAction(data: Omit<IApiRelative.IReplyComment.IParams, "parentId">) {
    return commentNote(
      {
        id: router.params.id
      },
      data
    )
  }
  /** 处理点评点赞成功回调 */
  function handleCommentLike(
    commentId: number,
    meta: IApiRelative.ISwitchCommentLike.IResData,
    parentId?: number
  ) {
    const _noteComments = state.noteComments.concat()
    if (!parentId) {
      // 顶级点评
      const finder = _noteComments.find(l => l.id === commentId)
      if (finder) {
        finder.isSelfLike = meta.isLike
        finder.likeCount = meta.likeCount
        setState({ noteComments: _noteComments })
      }
    } else {
      // 二级点评
      const finder = _noteComments.find(l => l.id === parentId)
      if (finder && finder.children) {
        const finder2 = finder.children.find(l => l.id === commentId)
        if (finder2) {
          finder2.isSelfLike = meta.isLike
          finder2.likeCount = meta.likeCount
          setState({ noteComments: _noteComments })
        }
      }
    }
  }
  /** 处理点评删除成功回调 */
  function handleCommentRemove(commentId: number, parentId?: number) {
    const _noteComments = state.noteComments.concat()
    if (!parentId) {
      // 顶级点评
      const index = _noteComments.findIndex(l => l.id === commentId)
      if (~index) {
        _noteComments.splice(index, 1)
        setState({ noteComments: _noteComments, commentCount: stateRef.current!.commentCount - 1 })
      }
    } else {
      // 二级点评
      const finder = _noteComments.find(l => l.id === parentId)
      if (finder && finder.children) {
        const index = finder.children.findIndex(l => l.id === commentId)
        if (~index) {
          finder.children.splice(index, 1)
          finder.childrenCount -= 1
          // ?删除二级评论是否会影响其他对该评论的子评论
          setState({ noteComments: _noteComments })
        }
      }
    }
  }
  /** 处理点评展开更多 */
  function expandCommentChildren(parentId?: number) {
    if (!parentId) return
    fetchNoteComments(parentId)
  }
  /** 处理笔记点赞/收藏 */
  function handleOpinionAction(actionType: "like" | "collect") {
    if (actionType === "like") {
      noteLikeSwitch({
        id: router.params.id
      }).then(res => {
        if (requestIsFullfilled(res)) {
          const { isLike, likeCount } = res.data.data
          Taro.showToast({
            title: isLike ? "点赞成功" : "已取消点赞",
            icon: "none"
          })
          const _detail = { ...state.detail }
          _detail.isSelfLike = isLike
          _detail.likeCount = likeCount
          setState({ detail: _detail })
          notePatchStack.push({
            id: Number(router.params.id),
            isSelfLike: isLike,
            likeCount
          })
        }
      })
    } else {
      switchNoteCollect({
        id: router.params.id
      }).then(res => {
        if (requestIsFullfilled(res)) {
          Taro.showToast({
            title: state.detail.isSelfFavorite ? "已取消收藏" : "收藏成功",
            icon: "none"
          })
          const _detail = { ...state.detail }
          _detail.isSelfFavorite = !_detail.isSelfFavorite
          _detail.favoriteCount = state.detail.isSelfFavorite
            ? _detail.favoriteCount - 1
            : _detail.favoriteCount + 1
          setState({ detail: _detail })
        }
      })
    }
  }
  function handleNoteLike(noteId: number, meta: IApiRelative.INoteLikeSwitch.IResData) {
    const _notes = state.detail.recommendNotes
    const finder = _notes.find(l => l.id === noteId)
    if (finder) {
      finder.isSelfLike = meta.isLike
      finder.likeCount = meta.likeCount
      setState({
        detail: {
          ...state.detail,
          recommendNotes: _notes
        }
      })
    }
  }
  function handleFilesPreview(url: string) {
    Taro.previewImage({
      current: url,
      urls: state.detail.files.map(l => l.fileImage)
    })
  }
  function onCommentSuccess(
    parentId: number,
    insertedComment: IApiRelative.IGetNoteComments.IGetNoteCommentItem,
    ownParentId: number
  ) {
    if (!insertedComment) {
      console.info("评论成功后接口没返回该新增评论项！")
      return
    }
    patchFields(insertedComment, insertedComment.childrenCount > 0)
    const _noteComments = state.noteComments.concat()
    if (!parentId) {
      _noteComments.unshift(insertedComment)
      setState({ noteComments: _noteComments, commentCount: stateRef.current!.commentCount + 1 })
    } else {
      const finder = _noteComments.find(l => l.id === ownParentId)
      if (finder && finder.children) {
        finder.children.unshift(insertedComment)
        finder.childrenCount += 1
        setState({ noteComments: _noteComments })
      }
    }
  }
  function renderAttachments() {
    if (!state.detail || state.detail.files.length === 0) return null
    return (
      <View className={styles.attatchments}>
        <Swiper
          style={{
            height: state.imageHeight + "px"
          }}
          className={styles.swiper}
          onChange={e => {
            setState({ currentImage: e.detail.current + 1 })
          }}
        >
          {state.detail.files.map((l, index) => (
            <SwiperItem
              key={l.id}
              className={styles.swiperItem}
              onClick={() => handleFilesPreview(l.fileImage)}
            >
              <Image
                style={
                  index === 0
                    ? state.extend
                      ? {
                          height: state.imageHeight + "px"
                        }
                      : {
                          width: "100%",
                          height: state.imageHeight + "px"
                        }
                    : { width: "100%", height: "100%" }
                }
                className={styles.swiperImage}
                src={l.fileImage}
                mode={index === 0 ? (state.extend ? "heightFix" : "scaleToFill") : "aspectFit"}
                onLoad={() => {
                  console.info("笔记详情图片加载事件", l.fileImage)
                }}
                onError={e => {
                  console.info("笔记详情图片加载失败事件", l.fileImage, e.detail.errMsg)
                }}
              />
            </SwiperItem>
          ))}
        </Swiper>
        <View className={styles.attatchmentsBottom}>
          {state.currentImage}/{state.detail.files.length}
        </View>
      </View>
    )
  }
  function renderRelatedTags() {
    if (state.detail.tagValues.length === 0) return
    return state.detail.tagValues.map(l => (
      <View
        style={{
          color: "#1B3C81"
        }}
        className="inline pr-8px"
        key={l.value}
        onClick={() => navigation(pageMapperCommunity.NoteTag, { id: l.value })}
      >
        #{l.label}
      </View>
    ))
  }
  /* 笔记关联的相关话题 */
  function renderRelatedTopics() {
    if (
      !state.detail ||
      !state.detail.relationDiscussions ||
      state.detail.relationDiscussions.length === 0
    )
      return null
    return (
      <View className={styles.relatedWords}>
        {state.detail.relationDiscussions.map(l => (
          <GpWordItem
            key={l.id}
            wordItem={{
              id: l.id,
              name: l.title
            }}
          />
        ))}
      </View>
    )
  }
  function renderDetail() {
    if (!state.detail) return null
    // 是否有关联模块
    const hasModule = state.detail.modules.length !== 0
    const [flowModule] = state.detail.modules || []
    const frgCount = state.detail.contentFragments.length
    const fromWord = router.params.from === "worddetail"
    return (
      <View
        className={clsx(styles.detailContent, {
          [styles.fromWord]: fromWord
        })}
      >
        <View className={styles.infoBlock}>
          <View
            className="flex flex-row items-center box-border"
            onClick={() =>
              navigation(pageMapperCommunity.PersonalPage, { id: state.detail.miniVisitorId })
            }
          >
            <Image
              className={styles.avatar}
              src={(state.detail.createdByHead as string) || process.env.__DEF_AVATAR__}
            />
            <View className={styles.info}>
              <View className={styles.name}>{state.detail.createdByName}</View>
              <View className={styles.concern}>{state.detail.followerCount}人关注</View>
            </View>
          </View>
          <View
            className={clsx(styles.concernBtn, {
              [styles.concerned]: state.detail.isSelfFollowing
            })}
            onClick={handleConcern}
          >
            {state.detail.isSelfFollowing ? "已关注" : "关注"}
          </View>
        </View>
        {/* 笔记标题 */}
        <View className={styles.noteTitle}>{state.detail.title}</View>
        {/* 笔记内容 */}
        <View
          className="text-bold text-30px font-normal leading-44px mt-32px"
          style={{
            wordWrap: "break-word"
          }}
        >
          {frgCount > 0
            ? state.detail.contentFragments.map((l, index) => (
                <View
                  key={index}
                  className={clsx("mb-36px text-justify", {
                    "mb-0": index === frgCount - 1
                  })}
                >
                  {l}
                  {index === frgCount - 1 ? renderRelatedTags() : null}
                </View>
              ))
            : renderRelatedTags()}
        </View>
        {/* 引流模块 */}
        {hasModule && (
          <GpFlowModule
            className="mt-32px"
            flowModule={{
              remark: flowModule.remark,
              description: flowModule.description,
              displayName: flowModule.displayName,
              id: flowModule.id,
              image: flowModule.cover,
              jumpPageId: flowModule.jumpPageId,
              jumpPageType: flowModule.jumpPageType,
              jumpType: flowModule.jumpType,
              jumpUrl: flowModule.jumpUrl,
              title: flowModule.name,
              isHide: flowModule.isHide
            }}
          />
        )}
        {renderRelatedTopics()}
        {/* 发布时间 */}
        <View className={styles.updateTime}>{state.detail.updatedTimeFormated}</View>
        <Divider
          style={{
            "--divider-color": fromWord ? "#FFFFFF" : "#F2F2F2",
            marginBottom: 0
          }}
        />
      </View>
    )
  }
  function renderComments() {
    if (state.commentCount === 0) return null
    const fromWord = router.params.from === "worddetail"
    return (
      <Fragment>
        <View
          className={clsx(styles.commentsLabel, {
            [styles.fromWord]: fromWord
          })}
        >
          共{state.commentCount}条评论
        </View>
        <View
          className={clsx(styles.comments, {
            [styles.fromWord]: fromWord
          })}
        >
          <View className={styles.commentList}>
            {/* 顶级评论项 */}
            {state.noteComments.map(l => (
              <GpComment
                key={l.id}
                comment={l}
                onLike={handleCommentLike}
                onExpandChildren={expandCommentChildren}
                onRemove={handleCommentRemove}
                onReply={handleReply}
                onReport={handleReport}
                className={styles.comment}
              />
            ))}
          </View>
        </View>
      </Fragment>
    )
  }
  /**
   * 1、随机推荐6篇笔记；
   * 2、推荐排序：同品类》同标签》同无品类无标签
   * @description 由于推荐笔记仅有6篇笔记, 要采用瀑布流, 目前不使用skyline, 采用左右列表显示即可
   * @reference http://192.168.18.237/%E3%80%902024-2-2%E3%80%91%E8%89%BA%E8%80%832.0%E7%A4%BE%E5%8C%BA/#id=y5o0cb&p=%E7%AC%94%E8%AE%B0%E8%AF%A6%E6%83%85_1&g=1&%E5%9B%BE%E7%89%87%E5%88%86%E4%BA%AB
   */
  function renderRecommands() {
    const list = state.detail.recommendNotes
    if (!list || list.length === 0) return null
    const left = [] as IApiRelative.IGetNoteDetail.INoteDetail["recommendNotes"]
    const right = [] as IApiRelative.IGetNoteDetail.INoteDetail["recommendNotes"]
    for (let i = 0; i < list.length; i++) {
      if (i % 2 === 0) {
        left.push(list[i])
      } else {
        right.push(list[i])
      }
    }
    return (
      <View className={styles.recommands}>
        <View className={styles.recommanLabel}>相关推荐</View>
        <View className={styles.recommandsList}>
          <View className={styles.recommandsPart}>
            {left.map(l => (
              <GpNoteItem
                skyline={false}
                key={l.id}
                noteItem={{
                  image: l.cover,
                  title: l.title,
                  avatar: l.createdByHead,
                  name: l.createdByName,
                  likes: l.likeCount,
                  liked: l.isSelfLike,
                  fileType: l.fileType,
                  id: l.id,
                  actionFlag: false,
                  videoFlag: true,
                  content: l.description
                }}
                onLike={(nodeItem, meta) => handleNoteLike(nodeItem.id, meta)}
              />
            ))}
          </View>
          <View className={styles.recommandsPart}>
            {right.map(l => (
              <GpNoteItem
                skyline={false}
                key={l.id}
                noteItem={{
                  image: l.cover,
                  title: l.title,
                  avatar: l.createdByHead,
                  name: l.createdByName,
                  likes: l.likeCount,
                  liked: l.isSelfLike,
                  fileType: l.fileType,
                  id: l.id,
                  actionFlag: false,
                  videoFlag: true,
                  content: l.description
                }}
                onLike={(nodeItem, meta) => handleNoteLike(nodeItem.id, meta)}
              />
            ))}
          </View>
        </View>
      </View>
    )
  }
  /**
   * 更多回答
   *
   * 6个回答：该话题下3个热度高，3个最新（热度计算参考社区页面）
   * @description 渲染从话题详情点击进入时渲染更多关联该同一话题的笔记
   * @reference http://192.168.18.237/%E3%80%902024-2-2%E3%80%91%E8%89%BA%E8%80%832.0%E7%A4%BE%E5%8C%BA/#id=fy9oz6&p=%E7%AC%94%E8%AE%B0%E8%AF%A6%E6%83%85&g=1&%E5%9B%BE
   */
  function renderMoreNote() {
    const notes = state.detail.recommendNotes
    if (notes.length === 0) return null
    return (
      <View
        className="mt-16px bg-white"
        style={{
          borderRadius: "16px 16px 0 0"
        }}
      >
        <View className="text-bold text-36px font-500 p-32px pb-0">更多回答</View>
        <View className="box-border px-32px">
          {notes.map(l => (
            <NoteAnswer key={l.id} note={l} onLike={handleNoteLike} className={styles.noteAnswer} />
          ))}
        </View>
      </View>
    )
  }
  return (
    <GpContainer className="min-h-screen" pageGap={152} shareConfig={{ title: state.detail.title }}>
      <View className={styles.noteDetail}>
        {/* 短评不显示附件图片 */}
        {state.detail.isShort ? null : renderAttachments()}
        {renderDetail()}
        {renderComments()}
        {router.params.from === "worddetail" ? renderMoreNote() : renderRecommands()}
        {/* @ts-ignore */}
        <GpOpinion
          ref={opinionRef as any}
          topCommentAction={topCommentAction}
          likeCount={state.detail.likeCount}
          collectCount={state.detail.favoriteCount}
          onAction={handleOpinionAction}
          isLike={state.detail.isSelfLike}
          isCollect={state.detail.isSelfFavorite}
          onConfirm={onCommentSuccess}
        />
      </View>
    </GpContainer>
  )
}
